<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2024/3/20
 * Time: 11:46
 */

namespace app\queue\generatedoverseawork;

use app\common\lib\Common;
use app\common\lib\Constant;
use app\common\lib\DetectFaceAdvance;
use app\common\lib\Guzzle;
use app\common\lib\MoyinTts;
use app\common\lib\RedisQueue;
use app\common\lib\TencentTts;
use app\exception\IndexException;
use app\logic\index\user\UserPromotionOverseaRollingImgLogic;
use app\model\consume\ConsumePointLogModel;
use app\model\image\ImageModelModel;
use app\model\novel\NovelChapterModel;
use app\model\novel\NovelChapterPartModel;
use app\model\plan\PromotionPlanModel;
use app\model\plan\PromotionPlanPartImageModel;
use app\model\queue\AiImageRequestQueueModel;
use app\model\redis\RedisQueueModel;
use app\model\tencent\TimbreModel;
use app\model\user\UserNovelChapterPartModel;
use app\model\user\UserPointFlowModel;
use app\model\user\UserPromotionOverseaModel;
use app\model\user\UserPromotionPlanModel;
use app\model\novel\NovelPlanRoleModel;
use support\Cache;
use support\Db;
use Webman\RedisQueue\Consumer;
use app\common\lib\TencentCos;

class GeneratedOverseaVideo  implements Consumer
{
    // 要消费的队列名
    public $queue = 'generatedOverseaVideo';

    // 连接名，对应 plugin/webman/redis-queue/redis.php 里的连接`
    public $connection = 'default';

    protected $resultData = [];

    // 消费
    public function consume($data)
    {
        Common::initQueueConfig();

        $queue = RedisQueueModel::getInstance()->find($data['queueid']);
        $queue->exec_time = date('Y-m-d H:i:s');
        $queue->save();

        try{
            // 无需反序列化
            $result = $this->handle($data);

            RedisQueue::getInstance()->saveQueue($this->queue,$data,$result);
        }catch (IndexException $e){
            //生成失败处理
            $this->generatedFail($data,$e);

            RedisQueue::getInstance()->saveQueue($this->queue,$data,['error'=>$e->getMessage()]);
            Common::queueExecptionReport($queue,$data,$e);
        }catch (\Throwable $e){
            //生成失败处理
            $this->generatedFail($data,$e);

            RedisQueue::getInstance()->saveQueue($this->queue,$data,['error'=>$e->getMessage()]);
            Common::queueExecptionReport($queue,$data,$e);
        }
    }

    protected function handle($data)
    {
        //todo 1 加入队列状态变更
        $userPlan = UserPromotionPlanModel::getInstance()->find($data['user_planid']);
        $userPlan->queue_time = date('Y-m-d H:i:s');
        $userPlan->status = 1;
        $userPlan->message = '生成中';
        $userPlan->save();

        //todo 2 生成创作内容片段-配音
        $requestId = $this->generatedTimbre($data);

        //卡片简介总结内容配置
        if (in_array($userPlan->style_type, [3, 4]) && !empty($userPlan->card_content)){
            //卡片
            $cardContentRequestId = $this->generatedCardContentTimbre($data);
        }


        //生成滚动字幕图片
        if ($userPlan['style_type'] == 2) {
            $overseaData = UserPromotionOverseaModel::getInstance()->find($userPlan->overseaid, ['content']);
            if ($overseaData) {
                UserPromotionOverseaRollingImgLogic::getInstance()->textToImg($userPlan->user_sn, $data['user_planid'], $overseaData->content);
            }
        }

        //todo 4 执行完成状态变更-延迟1秒在读取状态
        sleep(1);
        $isFinish = 1;
        $userPlanParts = UserNovelChapterPartModel::getInstance()->getWhere(['user_planid'=>$data['user_planid']])->orderBy('number','asc')->get();
        foreach ($userPlanParts as $val){
            if(empty($val['timbre_voice_url'])){
                $isFinish = 2;
                break;
            }
        }

        if($isFinish===1){
            $userPlan = UserPromotionPlanModel::getInstance()->find($data['user_planid']);
            $userPlan->finish_time = date('Y-m-d H:i:s');
            $userPlan->status = 2;
            $userPlan->message = '生成成功';
            $userPlan->save();
        }elseif($isFinish===2){
            $n=0;
            //等待配音完成
            while (true){
                $status = RedisQueueModel::getInstance()->getWhere(['name'=>'generateTimbre',['data','like',"%{$requestId}%"]])->value('status');
                if($status==2){
                    throw new IndexException(4020,'作品配音合成失败');
                }elseif($status==1){
                    $userPlan = UserPromotionPlanModel::getInstance()->find($data['user_planid']);
                    $userPlan->finish_time = date('Y-m-d H:i:s');
                    $userPlan->status = 2;
                    $userPlan->message = '生成成功';
                    $userPlan->save();
                    break;
                }
                if($n>600){
                    throw new IndexException(4020,'作品配音合成超时');
                }
                $n++;
                sleep(1);
            }
        }

        return ['success'];
    }

    protected function generatedTimbre($data)
    {
        //队列名
        $queue = 'generateTimbre';
        $requestId = Common::getRequestId();

        // 数据，可以直接传数组，无需序列化
        $data = ['requestid'=>$requestId, 'user_planid'=>$data['user_planid'], 'source'=>'generate_work'];

        // 投递消息
        RedisQueue::getInstance()->sendQueue($queue, $data);

        return $requestId;
    }

    protected function generatedCardContentTimbre($data)
    {
        //队列名
        $queue = 'generateTimbre';
        $requestId = Common::getRequestId();

        // 数据，可以直接传数组，无需序列化
        $data = ['requestid'=>$requestId, 'user_planid'=>$data['user_planid'], 'source'=>'generate_work_card_content'];

        // 投递消息
        RedisQueue::getInstance()->sendQueue($queue, $data);

        return $requestId;
    }

    /**
     * 生成失败处理
     * @param $data
     * @param $e
     * @return bool
     * @throws \Throwable
     */
    protected function generatedFail($data,$e)
    {
        try{
            Db::connection('mysql')->beginTransaction();
            $userPlan = UserPromotionPlanModel::getInstance()->find($data['user_planid']);
            $userPlan->finish_time = date('Y-m-d H:i:s');
            $userPlan->status = 3;
            $userPlan->message =mb_substr($e->getMessage(),0,255);
            $userPlan->save();

            //生成失败 退还点数
            $where = [
                'source_table'=>UserPromotionPlanModel::getInstance()->getTable(),
                'sourceid'=>$userPlan['id'],
                'user_sn'=>$userPlan['user_sn'],
            ];
            $consumeId = ConsumePointLogModel::getInstance()->getWhere($where)->value('id');

            if($consumeId){
                $where = [
                    'source_table'=>ConsumePointLogModel::getInstance()->getTable(),
                    'sourceid'=>$consumeId,
                    'user_sn'=>$userPlan['user_sn'],
                    'way'=>2,
                ];
                $first = UserPointFlowModel::getInstance()->getWhere($where)->first();
                if($first){
                    $insert = [];
                    $insert['source_table'] = ConsumePointLogModel::getInstance()->getTable();
                    $insert['sourceid'] = $consumeId;
                    $insert['user_sn'] = $userPlan['user_sn'];
                    $insert['nums'] = abs($first['nums']);
                    $insert['type'] = $first['type'];
                    $insert['way'] = 1;
                    $insert['is_refund'] = 1;
                    UserPointFlowModel::getInstance()->insert($insert);
                }
            }

            Db::connection('mysql')->commit();
        }catch (\Throwable $e){
            Db::connection('mysql')->rollBack();
        }

        return true;
    }

    // 消费失败回调
    /*
    $package = [
        'id' => 1357277951, // 消息ID
        'time' => 1709170510, // 消息时间
        'delay' => 0, // 延迟时间
        'attempts' => 2, // 消费次数
        'queue' => 'send-mail', // 队列名
        'data' => ['to' => 'tom@gmail.com', 'content' => 'hello'], // 消息内容
        'max_attempts' => 5, // 最大重试次数
        'error' => '错误信息' // 错误信息
    ]
    */
    public function onConsumeFailure(\Throwable $e, $package)
    {
//        echo "consume failure\n";
//        echo $e->getMessage() . "\n";
//        // 无需反序列化
//        var_export($package);

        RedisQueue::getInstance()->saveQueue($this->queue,$package['data'],['error'=>$e->getMessage()]);
    }

}